package edu.krazy.client;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.LinkedList;
import java.util.Queue;

import edu.krazy.common.BasicClientMessage;
import edu.krazy.common.ClientState;

public class BasicClient extends Thread {
	
	private String mAddress;
	private int mPort;
	private int mState;
	private String mUsername;
	private boolean mRunning;
	private IOnServerMessage mListener;
	private LinkedList<BasicClientMessage> mQueue;
	private ObjectOutputStream out;
	
	
	
	public String getUsername() {
		return mUsername;
	}

	public IOnServerMessage getListener() {
		return mListener;
	}

	public void setListener(IOnServerMessage mListener) {
		this.mListener = mListener;
	}
	
	
	
	public int getClientState() {
		return mState;
	}

	public void setClientState(int State) {
		this.mState = mState;
	}
	
	public void addMessage(BasicClientMessage message){
		synchronized (mQueue) {
			mQueue.add(message);
		}		
	}

	public BasicClient(String username, String address, int port){
		mState = ClientState.NOT_CONNECTED;
		mQueue = new LinkedList<BasicClientMessage>();
		mUsername = username;
		mAddress = address;
		mPort = port;
	}

	@Override
	public void run() {
		mRunning = true;
		writeThread.start();
		try {
			Socket socket = new Socket(mAddress, mPort);
			ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
			out = new ObjectOutputStream(socket.getOutputStream());
			//send username
			out.writeUTF(mUsername);
			out.flush();
			
			while(mRunning){
				if(mListener != null){
					mListener.handleServerMessage(in.readInt(), in);
					/*try {
						sleep(50);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}*/
				}
				
			}
			
		} catch(SocketException e){
			
		}catch (UnknownHostException e) {
		
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		mListener = null;
		
		super.run();
	}
	
	protected void writeMessage(BasicClientMessage message){
		try {
			out.writeInt(message.getType());
			if(message.getData() != null){
				if(message.getData() instanceof String){
					out.writeUTF((String)message.getData());
				}else if(message.getData() instanceof Integer){
					out.writeInt((Integer)message.getData());
				}else{
					out.writeObject(message.getData());
				}
			}
			out.flush();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private Thread writeThread = new Thread(){

		@Override
		public void run() {
			while (mRunning){
				BasicClientMessage message;
				synchronized (mQueue) {
					if((message = mQueue.poll()) != null){
						writeMessage(message);
					}
				}
			}
			super.run();
		}
		
	};
}
